package cn.dglydrpy.study.spring.aop.aspectj;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;
/**
 * 
 * @author dglydrpy
 *
 */
@Component //可实例化对象
@Aspect  //表示切面类
public class AOPServiceAdvisor {
	
	//环绕增强通知:1.必须有返回值 (即原方法的返回值) 2.原方法必须有参数  3.参数对象调用方法
	@SuppressWarnings("finally")
	@Around("@annotation(cn.dglydrpy.study.spring.aop.aspectj.AOPServicePointCut)")
	//切点表达式:
	//execution(修饰符 返回类型 包.类.方法(参数)) 基于方法的切点表达式  *为任意  配置多个可使用逻辑运算符  && || 等
	// eg: "execution(* cn.dglydrpy.study.*.*(..))"
	//bean():基于javaBean,用beanId来定义切点,表示切该bean类中所有方法
	//within(全路径包.类)  基于类的切点定义
	public int adviseGetResult(ProceedingJoinPoint pjp) throws Throwable{
		//可通过pjp获取原始方法的属性  
		// 其它增强方式入参为JoinPoint jp
		// Object[] args = jp.getArgs();
		Object[] args = pjp.getArgs();
		if (args != null && args.length > 0 && args[0].getClass() == Integer.class) {
			
			System.out.println(pjp.getSignature()); //方法签名
			System.out.println("代理对象: "+pjp.getThis().getClass().getName());
			System.out.println("目标对象: "+pjp.getTarget().getClass().getName());
			System.out.println("参数值: "+ args[0]);
        }
		Object object = null;
		try {
			//前置增强通知  相当于@Before 但比@Before先执行
			System.out.println("##### 准备计算 #####");
			long start = System.currentTimeMillis();
			object = pjp.proceed();//表示调用业务的方法
			//无异常后置增强通知  相当于@AfterReturning 但是比任一个后置通知都先执行,出现异常时中断会导致不执行
			System.out.println("##### 计算完成 #####");
			long end = System.currentTimeMillis();
			System.out.println("用时"+(end-start)+"ms"); //第一次执行时因为准备文件时间较长 后面就正常了
		} catch (Exception e) {
			e.printStackTrace();
			//异常后置增强通知  相当于@AfterThrowing
			System.out.println("##### 出现异常 #####");
		} finally {
			//后置增强通知  相对于@After  可用于关闭资源等,一定是所有后置通知类型中最后执行的
			if (object == null) {
				return 0;
			}else{
				return (Integer) object;
			}
		}
	}
	
}
